iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 19
0
Software Development

從零開始學Python系列 第 19

[Day 19] 從零開始學Python - 日期與時間:你知不知道,我等到花兒也謝了

  • 分享至 

  • xImage
  •  

註:本文同步刊載在Medium,若習慣Medium的話亦可去那邊看呦!

接下來我們要聊到日期與時間的處理相關模組:
datetime跟time。
請想像一下,在人生當中,是不是常常有要算日子和時間的時候?
不論是算退伍還有多少天;
算紀念日520天是什麼時候;
算紀念日1000天是什麼時候;
算紀念日2000天是什麼時候......XD
我們可以利用Python的datetime模組來幫忙計算時間日期與時間差,
這樣子就不會在被問今天是什麼日子的時候答不出來了(吧)!

datetime當中就有date物件time物件
接下來的示範還是屬於datetime模組的範疇,
請大家不要跟後面的time模組搞混歐!
我們先來看看操作日期的date物件的用法:

>>> from datetime import date
>>> doubleten = date(2020, 10, 10) # 順序是年/月/日
>>> doubleten.year, doubleten.month, doubleten.day
(2020, 10, 10)
# 用isoformat()和str()都可以轉成用"-"連接的字串
>>> doubleten.isoformat(), str(doubleten)
('2020-10-10', '2020-10-10')
>>> today = date.today() # today()會取到今天
>>> str(today) # isoformat格式會補0
'2020-10-01'
# 2020-10-01是星期四,weekday的記法是0(星期一)~6(星期日)
# isoweekday的記法則是1(星期一)~7(星期日)
>>> today.weekday(), today.isoweekday()
(3, 4)
# strftime可用來格式化想要的顯示樣態和目標
>>> doubleten.strftime('%Y--%m--%d, WeekDay: %a')
'2020--10--10, WeekDay: Sat'

關於strftime以及後面常見的格式,
大體上會跟一般通用的表示法相同,
例如%Y代表年,%m代表月,%d代表日,%a則代表星期幾的縮寫;
其他還有%H(小時)、%M(分)、%S(秒)等等,
可以參考strftime() 和 strptime() Format Codes

datetime中的time物件操作方式也很類似:

>>> from datetime import time
>>> time() # datetime的time.time()預設是從0開始
datetime.time(0, 0)
>>> now = time()
>>> now.isoformat()
'00:00:00'
>>> now = time(0,0,0,38) # 最小單位到微秒(百萬分之一秒,也就是10e-6)
>>> now.microsecond # 取微秒
38
>>> now = time(hour=19, second=50)
>>> str(now)
'19:00:50'
>>> now.strftime('%H-%M') # 同樣可以適用strftime
'19-00'

或者,兩者都要的話,
可以直接使用datetime.datetime物件!

>>> from datetime import datetime
>>> datetime.today() # 現在的時間,計到微秒
datetime.datetime(2020, 10, 1, 17, 37, 7, 490703)
>>> datetime.utcnow() # UTC標準時間(所以台灣是+8,看出來了嗎?)
datetime.datetime(2020, 10, 1, 9, 37, 43, 823644)
# str這邊和isoformat就會有點不一樣了,isoformat會用"T"來分隔。
>>> str(datetime.now())
'2020-10-01 17:39:03.953659'
>>> datetime.now().isoformat()
'2020-10-01T17:39:23.671787'

讀者可能會問:
「不對阿,說好的算紀念日呢?」
要計算日期差距相關的處理,
我們要用到datetime的另一個物件:
timedelta
timedelta的建立很簡單,就是timedelta(時間差)。
下面我們假設小亦向阿啾在今年的情人節2/14告白並成功了
接下來我們先來算一下到現在(10/1)為止
他們已經經過了幾天,到後面的紀念日又還有多久呢?

>>> from datetime import date, datetime, time ,timedelta
>>> valentine = date(2020, 2, 14)
>>> today = date.today()
>>> romanticlen = today - valentine # date相減會變成timedelta
# 算一算交往時間吧!
>>> romanticlen
datetime.timedelta(days=230)
# 小亦要記得的幾個紀念日
>>> remember = [100, 200, 520, 1000, 2000]
# 注意timedelta也可以用乘上數字來和定點日期相加減計算,相當有彈性
>>> memorialday = [valentine + timedelta(days=i) for i in remember]
>>> memorialday # 咦?這時間怎麼好像有的已經過了?
[datetime.date(2020, 5, 24), datetime.date(2020, 9, 1), datetime.date(2021, 7, 1
8), datetime.date(2022, 11, 10), datetime.date(2025, 8, 6)]
>>> diff = [i - today for i in memorialday] # 來減看看!
>>> diff # 小亦你很糟糕歐,有兩個紀念日已經過了!阿啾會哭哭呦XD
[datetime.timedelta(days=-130), datetime.timedelta(days=-30), datetime.timedelta
(days=290), datetime.timedelta(days=770), datetime.timedelta(days=1770)]

講完了datetime,我們現在來講time模組。
time模組比較簡單一點點,基本上最常用到的就是time.time()。
time.time()會給出Unix標準時間
也就是以1970年1月1號起算到目前為止帶小數點的總秒數(不用背,不會考XD)。
如果使用localtime()的話,則會換算成現在所在時區的時間。

>>> import time
>>> time.time()
1601547391.7189288
>>> time.localtime() # 筆者電腦目前是2020年10月1日下午6點16分
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=1, tm_hour=18, tm_min=16, tm_s
ec=34, tm_wday=3, tm_yday=275, tm_isdst=0)

上面範例中的struct_time是time的另一個物件,
作用是可以用來給定一個指定的時間方便處理。
我們也可以使用time.ctime()或time.strftime(格式化字串, 時間),
將其轉換成易讀的字串。

>>> now = time.localtime()
>>> time.ctime()
'Thu Oct  1 18:22:46 2020'
>>> time.strftime('現在是%A, %Y年%m月%d日的%H時%M分%S秒', now)
'現在是Thursday, 2020年10月01日的18時22分35秒'

不同的國家語系,給出來的縮寫等會不同,
如果要再精細轉換的話,可以使用local進行setlocale()的操作,
有興趣的話,可以再進一步研究一下用法。

但最常被簡單用到的方式還是time.time()跟time.sleep()了!
通常狀況下,我們會在跑完一段想測量的程式以後,
使用time.time()的差值來計算時間。
time.sleep()則可以讓程式暫時停止執行指定的秒數
待時間到才繼續運作。
我們拿前面的os的程式來修改一下測試這兩個方法,
會發現多次測試下,扣掉10秒以後,(因為10秒是我們睡掉的XD)
耗時其實差距蠻大的。
要取得一個比較良好的數據,
就可能要用迴圏來多測幾次,再取平均值。

import os, time
start = time.time()
for path, dirs, files in os.walk('.'):
    print(path)
    for f in files:
        print(os.path.join(path, f))		
		
    for d in dirs:
        print(os.path.join(path, d))
time.sleep(10) # 睡10秒鐘(可以給小數)
end = time.time()

print("總耗時:%f" % (end - start))
C:\Users\Desolve\utils>python fromzero.py
.
.\bookstore.json
.\check.py
.\fromzero.py
.\poem.txt
.\schedule.py
.\__init__.py
.\csv
.\json
.\__pycache__
.\csv
.\csv\student.csv
.\csv\student_dic.csv
.\json
.\json\classA.json
.\__pycache__
.\__pycache__\check.cpython-38.pyc
.\__pycache__\schedule.cpython-38.pyc
.\__pycache__\__init__.cpython-38.pyc
總耗時:10.003572

C:\Users\Desolve\utils>python fromzero.py
.
.\bookstore.json
.\check.py
.\fromzero.py
.\poem.txt
.\schedule.py
.\__init__.py
.\csv
.\json
.\__pycache__
.\csv
.\csv\student.csv
.\csv\student_dic.csv
.\json
.\json\classA.json
.\__pycache__
.\__pycache__\check.cpython-38.pyc
.\__pycache__\schedule.cpython-38.pyc
.\__pycache__\__init__.cpython-38.pyc
總耗時:10.002572

最後我們來做個練習吧!

  1. 承前面小亦和阿啾的狀況需要補救,
    請幫其重新列出接下來到明年(2021)幾個重要的節日的時間,
    計算距離2020-10-01的天數,並排序將其從近排到遠
    這樣小亦才不會漏掉。(1000天或2000天什麼的先不用算)
    [七夕(2021-08-14)、情人節(2021-02-14)、白色情人節(2021-03-14)、阿啾生日(2020-10-03)、阿啾生日(2021-10-03)]
    (什麼?你說為什麼有兩個生日?生日當然要每個生日都要過阿,
    會問這個問題的讀者請檢討一下自己是不是憑實力單身阿XD?)

那麼,我們就明天見囉!


上一篇
[Day 18] 從零開始學Python - 系統模組:走路的不是強尼,是你心中的OS
下一篇
[Day 20] 從零開始學Python - 時間量測與效率檢驗:你的時間也不是你的時間
系列文
從零開始學Python30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言